/*
	Copyright (C) 2009 Salil Bhagurkar
	
	This file is part of ViSE
	
	ViSE is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	ViSE is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.
	
	You should have received a copy of the GNU Lesser General Public License
	along with ViSE.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <shared.h>

/*Node creation functions*/

u32 data_type_size[] = {1, 2, 4, 8};

static u32 null_data;

void *create_data (u8 data_type, u32 count)
{
	if(data_type == DATA_TYPE_VOID)
		return &null_data;
	return malloc( data_type_size[data_type] * count );
}

struct node *create_node(u8 type, u8 data_type, u32 count, char *name)
{
	struct node *n;
	int i;
	n = (struct node *)malloc(sizeof(struct node));
	n->type = type;
	n->data_type = data_type;
	strcpy(n->name, name);
	n->data = create_data(data_type, count);
	for(i=0; i<NR_SERVERS; i++)
		n->server[i] = NULL;
	for(i=0; i<NR_CLIENTS; i++)
		n->client[i] = NULL;
	return n;
}

#define min(a,b) a < b ? a : b

void service(struct node *node)
{
	u32 transfer_count;
	struct node_fs *fs;
	int i;
	//Get data from server first
	for(i=0; i<NR_SERVERS; i++) {
		if(node->server[i]) {
			if(node->server[i]->type & TYPE_FSMASK) { //Read from a kernel mode system
				fs = (struct node_fs *)node->server[i];
				fs->read(fs, node->data, 0, node->count * data_type_size[node->data_type]);
			}
			if(node->data_type == node->server[i]->data_type) {
				service(node->server[i]);
				transfer_count = min(node->count, node->server[i]->count);
				memcpy(node->data, node->server[i]->data, transfer_count * data_type_size[node->data_type]);
			}
		} else
			break;
	}
	for(i=0; i<NR_CLIENTS; i++) {
		if(node->client[i]) {
			if(node->client[i]->type & TYPE_FSMASK) { //Read from a kernel mode system
				fs = (struct node_fs *)node->client[i];
				fs->write(fs, node->data, 0, node->count * data_type_size[node->data_type]);
			}
			if(node->data_type == node->client[i]->data_type) {
				transfer_count = min(node->count, node->client[i]->count);
				memcpy(node->client[i]->data, node->data, transfer_count * data_type_size[node->data_type]);
				service(node->client[i]);
			}
		} else
			break;
	}
}

void setup_program()
{
	struct node *n, *n1;
	n = create_node(TYPE_VDATA, DATA_TYPE_BYTE, 40, "test");
	strcpy(n->data, "Hello root from /user/msg\n");
	n->client[0] = (struct node *)fs_get("/user/msg");
	service(n);
}


void vinit()
{
	int i;
	init_malloc();
	register_class();
	register_event_ss();
	register_drivers();
	register_user();
	fs();
	setup_program();
	while(1) {
		service_events(0);
		arch_halt();
	}
}
